﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using System.IO;
using D = DocumentFormat.OpenXml.Drawing;
using P = DocumentFormat.OpenXml.Presentation;
using System.Xml;
namespace demo_ver2
{
    public class PptxHelper
    {
        private PresentationDocument presentationDoc;

        public PresentationDocument PresentationDoc
        {
            get { return presentationDoc; }
            set { presentationDoc = value; }
        }

        public PptxHelper(string filname)
        {
            this.presentationDoc = PresentationDocument.Open(filname, false);
        }

        public  int RetrieveNumberOfSlides()
        {
            PresentationPart presentationPart = this.presentationDoc.PresentationPart;
            int slidesCount = 0;
            if (presentationPart != null)
            {
                slidesCount = presentationPart.SlideParts.Count();
            }
            return slidesCount;
        }

        //cac ham lay title
        // Get a list of the titles of all the slides in the presentation.
        public List<string> GetSlideTitles()
        {
            
             return GetSlideTitles(this.presentationDoc);
           
        }

        // Get a list of the titles of all the slides in the presentation.
        public List<string> GetSlideTitles(PresentationDocument presentationDocument)
        {
            if (presentationDocument == null)
            {
                throw new ArgumentNullException("presentationDocument");
            }

            // Get a PresentationPart object from the PresentationDocument object.
            PresentationPart presentationPart = presentationDocument.PresentationPart;

            if (presentationPart != null &&
                presentationPart.Presentation != null)
            {
                // Get a Presentation object from the PresentationPart object.
                Presentation presentation = presentationPart.Presentation;

                if (presentation.SlideIdList != null)
                {
                    List<string> titlesList = new List<string>();

                    // Get the title of each slide in the slide order.
                    foreach (var slideId in presentation.SlideIdList.Elements<SlideId>())
                    {
                        SlidePart slidePart = presentationPart.GetPartById(slideId.RelationshipId) as SlidePart;

                        // Get the slide title.
                        string title = GetSlideTitle(slidePart);

                        // An empty title can also be added.
                        titlesList.Add(title);
                    }

                    return titlesList;
                }

            }

            return null;
        }

        // Get the title string of the slide.
        public static string GetSlideTitle(SlidePart slidePart)
        {
            if (slidePart == null)
            {
                throw new ArgumentNullException("presentationDocument");
            }

            // Declare a paragraph separator.
            string paragraphSeparator = null;

            if (slidePart.Slide != null)
            {
                // Find all the title shapes.
                var shapes = from shape in slidePart.Slide.Descendants<P.Shape>()
                             where IsTitleShape(shape)
                             select shape;

                StringBuilder paragraphText = new StringBuilder();

                foreach (var shape in shapes)
                {
                    // Get the text in each paragraph in this shape.
                    foreach (var paragraph in shape.TextBody.Descendants<D.Paragraph>())
                    {
                        // Add a line break.
                        paragraphText.Append(paragraphSeparator);

                        foreach (var text in paragraph.Descendants<D.Text>())
                        {
                            paragraphText.Append(text.Text);
                        }

                        paragraphSeparator = "\n";
                    }
                }

                return paragraphText.ToString();
            }

            return string.Empty;
        }

        // Determines whether the shape is a title shape.
        private static bool IsTitleShape(P.Shape shape)
        {
            var placeholderShape = shape.NonVisualShapeProperties.ApplicationNonVisualDrawingProperties.GetFirstChild<PlaceholderShape>();
            if (placeholderShape != null && placeholderShape.Type != null && placeholderShape.Type.HasValue)
            {
                switch ((PlaceholderValues)placeholderShape.Type)
                {
                    // Any title shape.
                    case PlaceholderValues.Title:

                    // A centered title.
                    case PlaceholderValues.CenteredTitle:
                        return true;

                    default:
                        return false;
                }
            }
            return false;
        }


        //lay text
        public string[] GetAllTextInSlide( int slideIndex)
        {
            // Verify that the presentation document exists.
            if (this.presentationDoc == null)
            {
                throw new ArgumentNullException("presentationDocument");
            }

            // Verify that the slide index is not out of range.
            if (slideIndex < 0)
            {
                throw new ArgumentOutOfRangeException("slideIndex");
            }

            // Get the presentation part of the presentation document.
            PresentationPart presentationPart = presentationDoc.PresentationPart;

            // Verify that the presentation part and presentation exist.
            if (presentationPart != null && presentationPart.Presentation != null)
            {
                // Get the Presentation object from the presentation part.
                Presentation presentation = presentationPart.Presentation;

                // Verify that the slide ID list exists.
                if (presentation.SlideIdList != null)
                {
                    // Get the collection of slide IDs from the slide ID list.
                    var slideIds = presentation.SlideIdList.ChildElements;

                    // If the slide ID is in range...
                    if (slideIndex < slideIds.Count)
                    {
                        // Get the relationship ID of the slide.
                        string slidePartRelationshipId = (slideIds[slideIndex] as SlideId).RelationshipId;

                        // Get the specified slide part from the relationship ID.
                        SlidePart slidePart = (SlidePart)presentationPart.GetPartById(slidePartRelationshipId);

                        // Pass the slide part to the next method, and
                        // then return the array of strings that method
                        // returns to the previous method.
                        return GetAllTextInSlide(slidePart);
                    }
                }
            }
            // Else, return null.
            return null;
        }


        public string[] GetAllTextInSlide(SlidePart slidePart)
        {
            // Verify that the slide part exists.
            if (slidePart == null)
            {
                throw new ArgumentNullException("slidePart");
            }

            // Create a new linked list of strings.
            LinkedList<string> texts = new LinkedList<string>();

            // If the slide exists...
            if (slidePart.Slide != null)
            {

               // getSlideContent(slidePart.Slide);
                // Iterate through all the paragraphs in the slide.
                foreach (var paragraph in slidePart.Slide.Descendants<DocumentFormat.OpenXml.Drawing.Paragraph>())
                {
                    // Create a new string builder.                    
                    StringBuilder paragraphText = new StringBuilder();

                    // Iterate through the lines of the paragraph.
                    foreach (var text in paragraph.Descendants<DocumentFormat.OpenXml.Drawing.Text>())
                    {
                        // Append each line to the previous lines.
                        paragraphText.Append(text.Text);
                    }

                    if (paragraphText.Length > 0)
                    {
                        // Add each paragraph to the linked list.
                        texts.AddLast(paragraphText.ToString());
                    }
                }
            }

            if (texts.Count > 0)
            {
                // Return an array of strings.
                return texts.ToArray();
            }
            else
            {
                return null;
            }
        }


        //lay text tu biet

        public MySlide MyGetAllTextInSlide(int slideIndex)
        {
            // Verify that the presentation document exists.
            if (this.presentationDoc == null)
            {
                throw new ArgumentNullException("presentationDocument");
            }

            // Verify that the slide index is not out of range.
            if (slideIndex < 0)
            {
                throw new ArgumentOutOfRangeException("slideIndex");
            }

            // Get the presentation part of the presentation document.
            PresentationPart presentationPart = presentationDoc.PresentationPart;
           
            
            // Verify that the presentation part and presentation exist.
            if (presentationPart != null && presentationPart.Presentation != null)
            {
                // Get the Presentation object from the presentation part.
                Presentation presentation = presentationPart.Presentation;

                //var textStyle = presentationPart.SlideMasterParts.ElementAt(0).SlideMaster.TextStyles.TitleStyle.Level1ParagraphProperties.Descendants<D.DefaultRunProperties>().First<D.DefaultRunProperties>();
                //double size = textStyle.FontSize;

                    SlideMaster slideMaster = presentationPart.SlideMasterParts.ElementAt(0).SlideMaster;
                // Verify that the slide ID list exists.
                if (presentation.SlideIdList != null)
                {
                    // Get the collection of slide IDs from the slide ID list.
                    var slideIds = presentation.SlideIdList.ChildElements;
                    
                    // If the slide ID is in range...
                    if (slideIndex < slideIds.Count)
                    {
                        // Get the relationship ID of the slide.
                        string slidePartRelationshipId = (slideIds[slideIndex] as SlideId).RelationshipId;
                      //  string slideLayOutRid = (slideLayouIds[slideIndex] as SlideLayoutId).RelationshipId;
                        // Get the specified slide part from the relationship ID.
                        SlidePart slidePart = (SlidePart)presentationPart.GetPartById(slidePartRelationshipId);
                        //slidePart.SlideLayoutPart.SlideLayout                   
                        
                        // Pass the slide part to the next method, and
                        // then return the array of strings that method
                        // returns to the previous method.
                        return MyGetAllTextInSlide(slidePart, slideMaster,slideIndex);
                        //return null;
                    }
                }
            }
            // Else, return null.
            return null;
        }

        public int CountTabIndent(double indent)
        {
            int rs = 0;
                          
                rs = (int)Math.Round(indent / 342900);
            
            return rs;
        }
        public MySlide MyGetAllTextInSlide(SlidePart slidePart, SlideMaster slideMaster,int slideId)
        {
            
            var textStyle = slideMaster.TextStyles.TitleStyle.Level1ParagraphProperties.Descendants<D.DefaultRunProperties>().First<D.DefaultRunProperties>();
            double sizelv1Title=3200.0;
            double sizelv2Title=2800.0;
            double sizelv1=2800.0;
            double sizelv2=2000.0;
            int tabIndent1 = 1 ;
            int tabIndent2=2;

            try
            {
                sizelv1Title = textStyle.FontSize;

                textStyle = slideMaster.TextStyles.TitleStyle.Level2ParagraphProperties.Descendants<D.DefaultRunProperties>().First<D.DefaultRunProperties>();
                sizelv2Title = textStyle.FontSize;

                textStyle = slideMaster.TextStyles.BodyStyle.Level1ParagraphProperties.Descendants<D.DefaultRunProperties>().First<D.DefaultRunProperties>();
                 sizelv1 = textStyle.FontSize;

                textStyle = slideMaster.TextStyles.BodyStyle.Level2ParagraphProperties.Descendants<D.DefaultRunProperties>().First<D.DefaultRunProperties>();
                sizelv2 = textStyle.FontSize;

                tabIndent1 = this.CountTabIndent(slideMaster.TextStyles.BodyStyle.Level1ParagraphProperties.LeftMargin);
                tabIndent2 = this.CountTabIndent(slideMaster.TextStyles.BodyStyle.Level2ParagraphProperties.LeftMargin);
            }
            catch { }
           // textStyle = slideMaster.TextStyles
            //string slideRS = "";
            MySlide slideRS = new MySlide();
            // Verify that the slide part exists.
            
            if (slidePart == null)
            {
                throw new ArgumentNullException("slidePart");
            }

            // If the slide exists...
            
            if (slidePart.Slide != null)
            {
                SlideLayoutPart layout = slidePart.SlideLayoutPart;
                
                //List<D.Level1ParagraphProperties> listLvl1 = slideLayout.SlideLayout.Descendants<D.Level1ParagraphProperties>().ToList<D.Level1ParagraphProperties>();
                //layout.DeleteParts<D.
                // getSlideContent(slidePart.Slide);
                // Iterate through all the paragraphs in the slide.
                
                
                var listShape = slidePart.Slide.Descendants<P.Shape>();
                int count = slidePart.Slide.Descendants<P.Picture>().Count();
                int count1 = slidePart.Slide.Descendants<P.GroupShape>().Count();
                foreach( var shape in listShape)
                {
                    PlaceholderShape placeholder =  shape.NonVisualShapeProperties.ApplicationNonVisualDrawingProperties.PlaceholderShape;

                    if (placeholder!= null && placeholder.Type != null)
                    {
                        switch ((PlaceholderValues)placeholder.Type)
                        {
                            case PlaceholderValues.Title:
                            // A centered title.
                            case PlaceholderValues.CenteredTitle:
                                {
                                    var listParagraphs = shape.TextBody.Descendants<D.Paragraph>();
                                    foreach (var paragraph in listParagraphs)
                                    {
                                        MyParagraph myparagraph = new MyParagraph();
                                        List<D.Text> listText = paragraph.Descendants<D.Text>().ToList<D.Text>();

                                        List<D.RunProperties> listRunProperties = paragraph.Descendants<D.RunProperties>().ToList<D.RunProperties>();
                                        for (int i = 0; i < listText.Count; i++)
                                        {
                                            if (listText[i].Text.Length > 0)
                                            {
                                                MyRow rowTemp = new MyRow(listText[i].Text);
                                                if (listRunProperties[i].FontSize != null)
                                                    rowTemp.FontSize = listRunProperties[i].FontSize;
                                                myparagraph.addRow(rowTemp);
                                            }
                                        }

                                        if (myparagraph.rowCount() > 0)
                                        {
                                            // Add each paragraph to the linked list.
                                            myparagraph.FontSize = sizelv1Title;
                                            slideRS.addParagraph(myparagraph);
                                        }
                                    }
                                }
                                break;


                            case PlaceholderValues.Footer:
                                {
                                    var listParagraphs = shape.TextBody.Descendants<D.Paragraph>();
                                    double shapeSizelvl1 = 8;
                                    if (shape.TextBody.ListStyle.Level1ParagraphProperties != null)
                                    {
                                        shapeSizelvl1 = shape.TextBody.ListStyle.Level1ParagraphProperties.Descendants<D.DefaultRunProperties>().First<D.DefaultRunProperties>().FontSize;
                                    }
                                    foreach (var paragraph in listParagraphs)
                                    {
                                        MyParagraph myparagraph = new MyParagraph();
                                        List<D.Text> listText = paragraph.Descendants<D.Text>().ToList<D.Text>();

                                        List<D.RunProperties> listRunProperties = paragraph.Descendants<D.RunProperties>().ToList<D.RunProperties>();
                                        for (int i = 0; i < listText.Count; i++)
                                        {
                                            if (listText[i].Text.Length > 0)
                                            {
                                                MyRow rowTemp = new MyRow(listText[i].Text);
                                                if (listRunProperties[i].FontSize != null)
                                                    rowTemp.FontSize = listRunProperties[i].FontSize;
                                                myparagraph.addRow(rowTemp);
                                            }
                                        }

                                        if (myparagraph.rowCount() > 0)
                                        {
                                            // Add each paragraph to the linked list.
                                           // myparagraph.FontSize = shapeSizelvl1;
                                            slideRS.addParagraph(myparagraph);
                                        }
                                    }
                                }
                                break;
                            default:
                                {
                                    var listParagraphs = shape.TextBody.Descendants<D.Paragraph>();
                                                                      
                                    foreach (var paragraph in listParagraphs)
                                    {
                                        MyParagraph myparagraph = new MyParagraph();
                                        List<D.Text> listText = paragraph.Descendants<D.Text>().ToList<D.Text>();

                                        List<D.RunProperties> listRunProperties = paragraph.Descendants<D.RunProperties>().ToList<D.RunProperties>();
                                        for (int i = 0; i < listText.Count; i++)
                                        {
                                            if (listText[i].Text.Length > 0)
                                            {
                                                MyRow rowTemp = new MyRow(listText[i].Text);
                                                if (listRunProperties[i].FontSize != null)
                                                    rowTemp.FontSize = listRunProperties[i].FontSize;
                                                myparagraph.addRow(rowTemp);
                                            }
                                        }

                                        if (myparagraph.rowCount() > 0)
                                        {
                                            // Add each paragraph to the linked list.

                                            slideRS.addParagraph(myparagraph);
                                        }
                                    }
                                }
                                break;
                        }
                    }
                    else
                    {
                        var listParagraphs = shape.TextBody.Descendants<D.Paragraph>();
                        foreach (var paragraph in listParagraphs)
                        {

                            MyParagraph myparagraph = new MyParagraph();

                            List<D.Text> listText = paragraph.Descendants<D.Text>().ToList<D.Text>();
                            if (paragraph.ParagraphProperties != null && paragraph.ParagraphProperties.Level != null)
                            {
                                int level = paragraph.ParagraphProperties.Level;
                                switch (level)
                                {
                                    case 1:
                                        myparagraph.FontSize = sizelv1;
                                        myparagraph.TabIndent = tabIndent1;
                                        break;
                                }
                            }
                            List<D.RunProperties> listRunProperties = paragraph.Descendants<D.RunProperties>().ToList<D.RunProperties>();
                            for (int i = 0; i < listText.Count; i++)
                            {
                                if (listText[i].Text.Length > 0)
                                {
                                    MyRow rowTemp = new MyRow(listText[i].Text);
                                    if (listRunProperties[i].FontSize != null)
                                        rowTemp.FontSize = listRunProperties[i].FontSize;
                                    myparagraph.addRow(rowTemp);
                                }
                            }

                            if (myparagraph.rowCount() > 0)
                            {
                                // Add each paragraph to the linked list.
                                
                                slideRS.addParagraph(myparagraph);
                            }
                        }
                    }
                        
                }
                   
               
            }

            // Return an array of strings.
            return slideRS;
        
        }
    }
}
